import sys
sys.path.append("..")
import pyrtl
from  pyrtl import GPUSim

OR1200_ASIC = True
ENDIANNESS = 'big'
#ENDIANNESS = 'little'

if OR1200_ASIC:
    OR1200_VIRTUALSILICON_SSP = True
    OR1200_DC_1W_8KB = True
    OR1200_DC_1W_4KB = False
    OR1200_NO_DC = False
else:
    OR1200_NO_DC = True
    OR1200_DC_1W_4KB = True
    OR1200_DC_1W_8KB = False

# Register OR1200 WISHBONE outputs
# (must be defined/enabled)
OR1200_REGISTERED_OUTPUTS = True

#WISHBONE Consecutive Address Burst
#This was used prior to WISHBONE B3 specification
#to identify bursts. It is no longer needed but
#remains enabled for compatibility with old designs.
OR1200_WB_CAB = True

#Enables default statement in some case blocks
#and disables Synopsys synthesis directive full_case
#By default it is enabled. When disabled it
#can increase clock frequency.
OR1200_CASE_DEFAULT = True

#Operand width / register file address width
#(DO NOT CHANGE)
OR1200_OPERAND_WIDTH = 32
OR1200_REGFILE_ADDR_WIDTH = 5

OR1200_ADDITIONAL_FLAG_MODIFIERS = False

#Implement l.addc/l.addic instructions
#By default implementation of l.addc/l.addic
#instructions is enabled in case you need them.
#If you don't use them, then disable implementation
#to save area.
OR1200_IMPL_ADDC = True

#Implement carry bit SR[CY]
#By default implementation of SR[CY] is enabled
#to be compliant with the simulator. However
#SR[CY] is explicitly only used by l.addc/l.addic
#instructions and if these two insns are not
#implemented there is not much point having SR[CY].
OR1200_IMPL_CY = True

#Type of ALU compare to implement
#Try either one to find what yields
#higher clock frequencyin your case.
#OR1200_IMPL_ALU_COMP1 = True
OR1200_IMPL_ALU_COMP2 = True

#Clock ratio RISC clock versus WB clock
#If you plan to run WB:RISC clock fixed to 1:1, disable
#both defines
#For WB:RISC 1:2 or 1:1, enable OR1200_CLKDIV_2_SUPPORTED
#and use clmode to set ratio
#For WB:RISC 1:4, 1:2 or 1:1, enable both defines and use
#clmode to set ratio
OR1200_CLKDIV_2_SUPPORTED = True
#OR1200_CLKDIV_4_SUPPORTED = True

#Type of register file RAM
#Memory macro w/ two ports (see or1200_tpram_32x32.v)
#OR1200_RFRAM_TWOPORT = True
#Memory macro dual port (see or1200_dpram_32x32.v)
#OR1200_RFRAM_DUALPORT = True
#Generic (flip-flop based) register file (see or1200_rfram_generic.v)
OR1200_RFRAM_GENERIC = True

#Type of mem2reg aligner to implement.
#Once OR1200_IMPL_MEM2REG2 yielded faster
#circuit, however with today tools it will
#most probably give you slower circuit.
OR1200_IMPL_MEM2REG1 = True
#OR1200_IMPL_MEM2REG2 = True

#ALUOPs
#Order defined by arith insns that have two source operands both in regs
OR1200_ALUOP_WIDTH = 4
OR1200_ALUOP_NOP = pyrtl.Const(4, bitwidth=OR1200_ALUOP_WIDTH)

OR1200_ALUOP_ADD, OR1200_ALUOP_ADDC, OR1200_ALUOP_SUB,\
        OR1200_ALUOP_AND, OR1200_ALUOP_OR, OR1200_ALUOP_XOR = [pyrtl.Const(x, bitwidth=OR1200_ALUOP_WIDTH) for x in range(6)]

OR1200_ALUOP_SHROT  = pyrtl.Const(8, bitwidth=OR1200_ALUOP_WIDTH)

#Order not specifically defined.
OR1200_ALUOP_IMM, OR1200_ALUOP_MOVHI, OR1200_ALUOP_COMP, OR1200_ALUOP_MTSR, OR1200_ALUOP_MFSR =\
        [pyrtl.Const(x, bitwidth=OR1200_ALUOP_WIDTH) for x in range(11, 16)]

OR1200_ALUOP_CMOV, OR1200_ALUOP_FF1 = [pyrtl.Const(x, bitwidth=OR1200_ALUOP_WIDTH) for x in range(14, 16)]

#MACOPs
OR1200_MACOP_WIDTH = 2
OR1200_MACOP_NOP, OR1200_MACOP_MAC, OR1200_MACOP_MSB = [pyrtl.Const(x, bitwidth=OR1200_MACOP_WIDTH) for x in range(3)]

#Shift/rotate ops
OR1200_SHROTOP_WIDTH = 2
OR1200_SHROTOP_NOP = pyrtl.Const(0, bitwidth=OR1200_SHROTOP_WIDTH)
OR1200_SHROTOP_SLL, OR1200_SHROTOP_SRL, OR1200_SHROTOP_SRA, OR1200_SHROTOP_ROR = [pyrtl.Const(x, bitwidth=OR1200_SHROTOP_WIDTH) for x in range(4)]

#Execution cycles per instruction
OR1200_MULTICYCLE_WIDTH = 2
OR1200_ONE_CYCLE, OR1200_TWO_CYCLES = [pyrtl.Const(x, bitwidth=OR1200_MULTICYCLE_WIDTH) for x in range(2)]

#Operand MUX selects
OR1200_SEL_WIDTH = 2
OR1200_SEL_RF, OR1200_SEL_IMM, OR1200_SEL_EX_FORW, OR1200_SEL_WB_FORW = [pyrtl.Const(x, bitwidth=OR1200_SEL_WIDTH) for x in range(4)]

#BRANCHOPs
OR1200_BRANCHOP_WIDTH = 3
OR1200_BRANCHOP_NOP, OR1200_BRANCHOP_J, OR1200_BRANCHOP_JR, \
    OR1200_BRANCHOP_BAL, OR1200_BRANCHOP_BF, OR1200_BRANCHOP_BNF, OR1200_BRANCHOP_RFE = [pyrtl.Const(x, bitwidth=OR1200_BRANCHOP_WIDTH) for x in range(7)]

#LSUOPs
#Bit 0: sign extend
#Bits 1-2: 00 doubleword, 01 byte, 10 halfword, 11 singleword
#Bit 3: 0 load, 1 store
OR1200_LSUOP_WIDTH = 4
OR1200_LSUOP_NOP, OR1200_LSUOP_LD, OR1200_LSUOP_LBZ, \
    OR1200_LSUOP_LBS, OR1200_LSUOP_LHZ, OR1200_LSUOP_LHS, \
    OR1200_LSUOP_LWZ, OR1200_LSUOP_LWS, OR1200_LSUOP_SD = [pyrtl.Const(x, bitwidth=OR1200_LSUOP_WIDTH) for x in range(9)]
OR1200_LSUOP_SB, OR1200_LSUOP_SH, OR1200_LSUOP_SW = [pyrtl.Const(x, bitwidth=OR1200_LSUOP_WIDTH) for x in range(10, 16, 2)]

#FETCHOPs
OR1200_FETCHOP_WIDTH = 1
OR1200_FETCHOP_NOP, OR1200_FETCHOP_LW = [pyrtl.Const(x, bitwidth=OR1200_FETCHOP_WIDTH) for x in range(2)]

#Register File Write-Back OPs
#Bit 0: register file write enable
#Bits 2-1: write-back mux selects
OR1200_RFWBOP_WIDTH = 3
OR1200_RFWBOP_NOP = pyrtl.Const(0, bitwidth=OR1200_RFWBOP_WIDTH)
OR1200_RFWBOP_ALU, OR1200_RFWBOP_LSU, OR1200_RFWBOP_SPRS, OR1200_RFWBOP_LR = [pyrtl.Const(x, bitwidth=OR1200_RFWBOP_WIDTH) for x in range(1, 9, 2)]

#Compare instructions
OR1200_COMPOP_WIDTH = 4
OR1200_SIGNED_COMPARE = pyrtl.Const(3)
OR1200_COP_SFEQ, OR1200_COP_SFNE, OR1200_COP_SFGT,\
    OR1200_COP_SFGE, OR1200_COP_SFLT, OR1200_COP_SFLE= [pyrtl.Const(x, bitwidth=OR1200_COMPOP_WIDTH-1) for x in range(6)]
OR1200_COP_X = pyrtl.Const(7, bitwidth=OR1200_COMPOP_WIDTH-1)

#TAGs for instruction bus
OR1200_ITAG_IDLE = pyrtl.Const(0x0, bitwidth=4) #idle bus
OR1200_ITAG_NI = pyrtl.Const(0x1, bitwidth=4)  #normal insn
OR1200_ITAG_BE = pyrtl.Const(0xb, bitwidth=4)  #Bus error exception
OR1200_ITAG_PE = pyrtl.Const(0xc, bitwidth=4)  #Page fault exception
OR1200_ITAG_TE = pyrtl.Const(0xd, bitwidth=4)  #TLB miss exception

#TAGs for data bus
OR1200_DTAG_IDLE = pyrtl.Const(0x0, bitwidth=4)	#idle bus
OR1200_DTAG_ND = pyrtl.Const(0x1, bitwidth=4)#normal data
OR1200_DTAG_AE = pyrtl.Const(0xa, bitwidth=4)#Alignment exception
OR1200_DTAG_BE = pyrtl.Const(0xb, bitwidth=4)#Bus error exception
OR1200_DTAG_PE = pyrtl.Const(0xc, bitwidth=4)#Page fault exception
OR1200_DTAG_TE = pyrtl.Const(0xd, bitwidth=4)#TLB miss exception

#ORBIS32 ISA specifics
#Verilog中原为7:6，取第6、7位，高位在右边，因此是从左边（下标0）数第6、7位
OR1200_SHROTOP_POS = slice(6, 8)# to be fixed
#ALU instructions multicycle field in machine word
OR1200_ALUMCYC_POS = slice(8, 10)

#Instruction opcode groups (basic)
OR1200_OR32_J = pyrtl.Const(0, bitwidth=6)
OR1200_OR32_JAL = pyrtl.Const(1, bitwidth=6)
OR1200_OR32_BNF = pyrtl.Const(3, bitwidth=6)
OR1200_OR32_BF = pyrtl.Const(4, bitwidth=6)
OR1200_OR32_NOP = pyrtl.Const(5, bitwidth=6)
OR1200_OR32_MOVHI = pyrtl.Const(6, bitwidth=6)
OR1200_OR32_XSYNC = pyrtl.Const(8, bitwidth=6)
OR1200_OR32_RFE = pyrtl.Const(9, bitwidth=6)

OR1200_OR32_JR = pyrtl.Const(17, bitwidth=6)
OR1200_OR32_JALR = pyrtl.Const(18, bitwidth=6)
OR1200_OR32_MACI = pyrtl.Const(19, bitwidth=6)

OR1200_OR32_LWZ = pyrtl.Const(33, bitwidth=6)
OR1200_OR32_LBZ = pyrtl.Const(35, bitwidth=6)
OR1200_OR32_LBS = pyrtl.Const(36, bitwidth=6)
OR1200_OR32_LHZ = pyrtl.Const(37, bitwidth=6)
OR1200_OR32_LHS = pyrtl.Const(38, bitwidth=6)
OR1200_OR32_ADDI = pyrtl.Const(39, bitwidth=6)
OR1200_OR32_ADDIC = pyrtl.Const(40, bitwidth=6)
OR1200_OR32_ANDI = pyrtl.Const(41, bitwidth=6)
OR1200_OR32_ORI = pyrtl.Const(42, bitwidth=6)
OR1200_OR32_XORI = pyrtl.Const(43, bitwidth=6)
OR1200_OR32_MFSPR = pyrtl.Const(45, bitwidth=6)
OR1200_OR32_SH_ROTI = pyrtl.Const(46, bitwidth=6)
OR1200_OR32_SFXXI = pyrtl.Const(47, bitwidth=6)

OR1200_OR32_MTSPR = pyrtl.Const(48, bitwidth=6)
OR1200_OR32_MACMSB = pyrtl.Const(49, bitwidth=6)

OR1200_OR32_SW = pyrtl.Const(53, bitwidth=6)
OR1200_OR32_SB = pyrtl.Const(54, bitwidth=6)
OR1200_OR32_SH = pyrtl.Const(55, bitwidth=6)
OR1200_OR32_ALU = pyrtl.Const(56, bitwidth=6)
OR1200_OR32_SFXX = pyrtl.Const(57, bitwidth=6)

# Exceptions

# Exception vectors per OR1K architecture:
# 0xPPPPP100 - reset
# 0xPPPPP200 - bus error
# ... etc
# where P represents exception prefix.
#
# Exception vectors can be customized as per
# the following formula:
# 0xPPPPPNVV - exception N
#
# P represents exception prefix
# N represents exception N
# VV represents length of the individual vector space,
#   usually it is 8 bits wide and starts with all bits zero
#
# PPPPP and VV parts
#
# Sum of these two defines needs to be 28
OR1200_EXCEPT_EPH0_P = pyrtl.Const(0x0, bitwidth=20)
OR1200_EXCEPT_EPH1_P = pyrtl.Const(0x0, bitwidth=20)
OR1200_EXCEPT_V = pyrtl.Const(0x0, bitwidth=8)

#N part width
OR1200_EXCEPT_WIDTH = 4

# Definition of exception vectors
#
# To avoid implementation of a certain exception,
# simply comment out corresponding line
OR1200_EXCEPT_UNUSED = pyrtl.Const(0xf, bitwidth=OR1200_EXCEPT_WIDTH)
OR1200_EXCEPT_TRAP = pyrtl.Const(0xe, bitwidth=OR1200_EXCEPT_WIDTH)		#0xe
OR1200_EXCEPT_BREAK = pyrtl.Const(0xd, bitwidth=OR1200_EXCEPT_WIDTH)		#0xd
OR1200_EXCEPT_SYSCALL = pyrtl.Const(0xc, bitwidth=OR1200_EXCEPT_WIDTH)		#0xc
OR1200_EXCEPT_RANGE = pyrtl.Const(0xb, bitwidth=OR1200_EXCEPT_WIDTH)		#0xb
OR1200_EXCEPT_ITLBMISS = pyrtl.Const(0xa, bitwidth=OR1200_EXCEPT_WIDTH)		#0xa
OR1200_EXCEPT_DTLBMISS = pyrtl.Const(0x9, bitwidth=OR1200_EXCEPT_WIDTH)		#0x9
OR1200_EXCEPT_INT = pyrtl.Const(0x8, bitwidth=OR1200_EXCEPT_WIDTH)		#0x8
OR1200_EXCEPT_ILLEGAL = pyrtl.Const(0x7, bitwidth=OR1200_EXCEPT_WIDTH)  #0x7
OR1200_EXCEPT_ALIGN = pyrtl.Const(0x6, bitwidth=OR1200_EXCEPT_WIDTH)		#0x6
OR1200_EXCEPT_TICK = pyrtl.Const(0x5, bitwidth=OR1200_EXCEPT_WIDTH) #0x5
OR1200_EXCEPT_IPF = pyrtl.Const(0x4, bitwidth=OR1200_EXCEPT_WIDTH)  #0x4
OR1200_EXCEPT_DPF = pyrtl.Const(0x3, bitwidth=OR1200_EXCEPT_WIDTH)  #0x3
OR1200_EXCEPT_BUSERR = pyrtl.Const(0x2, bitwidth=OR1200_EXCEPT_WIDTH)   #0x2
OR1200_EXCEPT_RESET = pyrtl.Const(0x1, bitwidth=OR1200_EXCEPT_WIDTH)    #0x1
OR1200_EXCEPT_NONE = pyrtl.Const(0x0, bitwidth=OR1200_EXCEPT_WIDTH) #0x0

#SPR groups
#Bits that define the group
OR1200_SPR_GROUP_BITS = slice(11, 16)	#15:11
#Width of the group bits
OR1200_SPR_GROUP_WIDTH = 5
#Bits that define offset inside the group
OR1200_SPR_OFS_BITS = slice(0, 11) #10:0

#List of groups
OR1200_SPR_GROUP_SYS = pyrtl.Const(0, bitwidth = 5)	#5'd00
OR1200_SPR_GROUP_DC = pyrtl.Const(3, bitwidth = 5)	#	5'd03
OR1200_SPR_GROUP_IC = pyrtl.Const(4, bitwidth = 5)	#	5'd04
OR1200_SPR_GROUP_DU = pyrtl.Const(6, bitwidth = 5)	#	5'd06
OR1200_SPR_GROUP_PM = pyrtl.Const(8, bitwidth = 5)	#	5'd08
OR1200_SPR_GROUP_PIC = pyrtl.Const(9, bitwidth = 5)	#	5'd09
OR1200_SPR_GROUP_TT = pyrtl.Const(10, bitwidth = 5)	#	5'd10

#System group
#System registers
OR1200_SPR_CFGR = pyrtl.Const(0, bitwidth=7)	#	7'd0
OR1200_SPR_RF = pyrtl.Const(32, bitwidth=6)	#		6'd32	# 1024 >> 5
OR1200_SPR_NPC = pyrtl.Const(16, bitwidth=11)	#		11'd16
OR1200_SPR_SR = pyrtl.Const(17, bitwidth=11)	#		11'd17
OR1200_SPR_PPC = pyrtl.Const(18, bitwidth=11)	#		11'd18
OR1200_SPR_EPCR = pyrtl.Const(32, bitwidth=11)	#		11'd32
OR1200_SPR_EEAR = pyrtl.Const(48, bitwidth=11)	#		11'd48
OR1200_SPR_ESR = pyrtl.Const(64, bitwidth=11)	#		11'd64

#SR bits
OR1200_SR_WIDTH = 16

OR1200_SR_SM, OR1200_SR_TEE, OR1200_SR_IEE, OR1200_SR_DCE, OR1200_SR_ICE, OR1200_SR_DME, \
    OR1200_SR_IME, OR1200_SR_LEE, OR1200_SR_CE, OR1200_SR_F, OR1200_SR_CY, OR1200_SR_OV, \
    OR1200_SR_OVE, OR1200_SR_DSX, OR1200_SR_EPH, OR1200_SR_FO = range(16)
OR1200_SR_CID = slice(28, 32) #31:28

#Bits that define offset inside the group
OR1200_SPROFS_BITS = slice(0, 11) #10:0

#Default Exception Prefix
# 1'b0 - OR1200_EXCEPT_EPH0_P (0x0000_0000)
# 1'b1 - OR1200_EXCEPT_EPH1_P (0xF000_0000)
OR1200_SR_EPH_DEF = pyrtl.Const(0, bitwidth=1)

# Power Management (PM)
# Define it if you want PM implemented
OR1200_PM_IMPLEMENTED = True

#Bit positions inside PMR (don't change)
OR1200_PM_PMR_SDF = slice(0, 4) #3:0
OR1200_PM_PMR_DME = 4
OR1200_PM_PMR_SME = 5
OR1200_PM_PMR_DCGE = 6
OR1200_PM_PMR_UNUSED = slice(7, 32) #31:7

#PMR offset inside PM group of registers
OR1200_PM_OFS_PMR = pyrtl.Const(0, bitwidth=11) #11'b0
#PM group
OR1200_SPRGRP_PM = pyrtl.Const(8, bitwidth=5) #5'd8
#Define if unused PMR bits should be zero
OR1200_PM_UNUSED_ZERO = True
#Define if PMR can be read/written at any address inside PM group
OR1200_PM_PARTIAL_DECODING = True
#Define if reading PMR is allowed
OR1200_PM_READREGS = True
#Debug Unit (DU)
#Define it if you want DU implemented
OR1200_DU_IMPLEMENTED = True

# Define if you want HW Breakpoints
# (if HW breakpoints are not implemented
# only default software trapping is
# possible with l.trap insn - this is
# however already enough for use
# with or32 gdb)
#
OR1200_DU_HWBKPTS = False

#Number of DVR/DCR pairs if HW breakpoints enabled
OR1200_DU_DVRDCR_PAIRS = 8
#Define if you want trace buffer
OR1200_DU_TB_IMPLEMENTED = False

# Address offsets of DU registers inside DU group
#
# To not implement a register, doq not define its address
if OR1200_DU_HWBKPTS:
    OR1200_DU_DVR0, OR1200_DU_DVR1, OR1200_DU_DVR2, OR1200_DU_DVR3, OR1200_DU_DVR4, OR1200_DU_DVR5, OR1200_DU_DVR6, OR1200_DU_DVR7 =\
        [pyrtl.Const(x, bitwidth=11) for x in range(8)]
    OR1200_DU_DCR0, OR1200_DU_DCR1, OR1200_DU_DCR2, OR1200_DU_DCR3, OR1200_DU_DCR4, OR1200_DU_DCR5, OR1200_DU_DCR6, OR1200_DU_DCR7 = \
        [pyrtl.Const(x, bitwidth=11) for x in range(8, 16)]
OR1200_DU_DMR1 = pyrtl.Const(16, bitwidth=11)

if OR1200_DU_HWBKPTS:
    OR1200_DU_DMR2, OR1200_DU_DWCR0, OR1200_DU_DWCR1 = [pyrtl.Const(x, bitwidth=11) for x in range(17, 20)]
OR1200_DU_DSR, OR1200_DU_DRR = [pyrtl.Const(x, bitwidth=11) for x in range(20, 22)]

if OR1200_DU_TB_IMPLEMENTED:
    OR1200_DU_TBADR = pyrtl.Const(0x0ff, bitwidth=11)
    OR1200_DU_TBIA, OR1200_DU_TBIM, OR1200_DU_TBAR, OR1200_DU_TBTS = [pyrtl.Const(0x0, bitwidth=11)] * 4

#Position of offset bits inside SPR address
OR1200_DUOFS_BITS = slice(0, 11)	#10:0

#DCR bits
OR1200_DU_DCR_DP = 0
OR1200_DU_DCR_CC = slice(1, 4) #3:1
OR1200_DU_DCR_SC = 4
OR1200_DU_DCR_CT = slice(5, 8) #7:5

#DMR1 bits
OR1200_DU_DMR1_CW0 = slice(0, 2) #1:0
OR1200_DU_DMR1_CW1 = slice(2, 4) #3:2
OR1200_DU_DMR1_CW2 = slice(4, 6) #5:4
OR1200_DU_DMR1_CW3 = slice(6, 8) #7:6
OR1200_DU_DMR1_CW4 = slice(8, 10) #9:8
OR1200_DU_DMR1_CW5 = slice(10, 12) #11:10
OR1200_DU_DMR1_CW6 = slice(12, 14) #13:12
OR1200_DU_DMR1_CW7 = slice(14, 16) #15:14
OR1200_DU_DMR1_CW8 = slice(16, 18) #17:16
OR1200_DU_DMR1_CW9 = slice(18, 20) #19:18
OR1200_DU_DMR1_CW10 = slice(20, 22) #21:20
OR1200_DU_DMR1_ST = 22
OR1200_DU_DMR1_BT = 23
OR1200_DU_DMR1_DXFW = 24
OR1200_DU_DMR1_ETE = 25

#DMR2 bits
OR1200_DU_DMR2_WCE0 = 0
OR1200_DU_DMR2_WCE1 = 1
OR1200_DU_DMR2_AWTC = slice(2, 13) #12:2
OR1200_DU_DMR2_WGB = slice(13, 24) #23:13

#DWCR bits
OR1200_DU_DWCR_COUNT = slice(0, 16) #15:0
OR1200_DU_DWCR_MATCH = slice(16, 32) #31:16

#DSR bits
OR1200_DU_DSR_RSTE, OR1200_DU_DSR_BUSEE, OR1200_DU_DSR_DPFE, OR1200_DU_DSR_IPFE, OR1200_DU_DSR_TTE, \
    OR1200_DU_DSR_AE, OR1200_DU_DSR_IIE, OR1200_DU_DSR_IE, OR1200_DU_DSR_DME, OR1200_DU_DSR_IME, \
    OR1200_DU_DSR_RE, OR1200_DU_DSR_SCE, OR1200_DU_DSR_BE, OR1200_DU_DSR_TE, OR1200_DU_DSR_WIDTH = range(15)

#DRR bits
OR1200_DU_DRR_RSTE, OR1200_DU_DRR_BUSEE, OR1200_DU_DRR_DPFE, OR1200_DU_DRR_IPFE, OR1200_DU_DRR_TTE, \
    OR1200_DU_DRR_AE, OR1200_DU_DRR_IIE, OR1200_DU_DRR_IE, OR1200_DU_DRR_DME, OR1200_DU_DRR_IME, \
    OR1200_DU_DRR_RE, OR1200_DU_DRR_SCE, OR1200_DU_DRR_BE, OR1200_DU_DRR_TE = range(14)

#Define if reading DU regs is allowed
OR1200_DU_READREGS = True
#Define if unused DU registers bits should be zero
OR1200_DU_UNUSED_ZERO = True
#Define if IF/LSU status is not needed by devel i/f
OR1200_DU_STATUS_UNIMPLEMENTED = True

#Programmable Interrupt Controller (PIC)

#Define it if you want PIC implemented
OR1200_PIC_IMPLEMENTED = True
#Define number of interrupt inputs (2-31)
OR1200_PIC_INTS = 20
#Address offsets of PIC registers inside PIC group
OR1200_PIC_OFS_PICMR = pyrtl.Const(0, bitwidth=2) #2'd0
OR1200_PIC_OFS_PICSR = pyrtl.Const(2, bitwidth=2) #2'd2
#Position of offset bits inside SPR address
OR1200_PICOFS_BITS = slice(0, 2)  # 1:0
#Define if you want these PIC registers to be implemented
OR1200_PIC_PICMR = True
OR1200_PIC_PICSR = True
#Define if reading PIC registers is allowed
OR1200_PIC_READREGS = True
#Define if unused PIC register bits should be zero
OR1200_PIC_UNUSED_ZERO = True

#Tick Timer (TT)
#Define it if you want TT implemented
OR1200_TT_IMPLEMENTED = True
#Address offsets of TT registers inside TT group
OR1200_TT_OFS_TTMR = pyrtl.Const(0, bitwidth=1) #1'd0
OR1200_TT_OFS_TTCR = pyrtl.Const(1, bitwidth=1) #1'd1
#Position of offset bits inside SPR group
OR1200_TTOFS_BITS = 0
#Define if you want these TT registers to be implemented
OR1200_TT_TTMR = True
OR1200_TT_TTCR = True
#TTMR bits
OR1200_TT_TTMR_TP = slice(0, 27) #27:0
OR1200_TT_TTMR_IP = slice(28, 29) #28
OR1200_TT_TTMR_IE = slice(29, 30) # 29
OR1200_TT_TTMR_M = slice(30, 32) #31:30
#Define if reading TT registers is allowed
OR1200_TT_READREGS = True

#Data cache (DC)
#3 for 8 bytes, 4 for 16 bytes etc
OR1200_DCLS = 4
#DC configurations
if OR1200_DC_1W_4KB:
    OR1200_DCSIZE = 12
    OR1200_DCINDX = OR1200_DCSIZE - 2
    OR1200_DCINDXH = OR1200_DCSIZE - 1
    OR1200_DCTAGL = OR1200_DCINDXH + 1
    OR1200_DCTAG = OR1200_DCSIZE - OR1200_DCLS
    OR1200_DCTAG_W = 21

if OR1200_DC_1W_8KB:
    OR1200_DCSIZE = 13
    OR1200_DCINDX = OR1200_DCSIZE - 2
    OR1200_DCINDXH = OR1200_DCSIZE - 1
    OR1200_DCTAGL = OR1200_DCINDXH + 1
    OR1200_DCTAG = OR1200_DCSIZE - OR1200_DCLS
    OR1200_DCTAG_W = 20


# Store buffer (SB)

# Store buffer
#
# It will improve performance by "caching" CPU stores
# using store buffer. This is most important for function
# prologues because DC can only work in write though mode
# and all stores would have to complete external WB writes
# to memory.
# Store buffer is between DC and data BIU.
# All stores will be stored into store buffer and immediately
# completed by the CPU, even though actual external writes
# will be performed later. As a consequence store buffer masks
# all data bus errors related to stores (data bus errors
# related to loads are delivered normally).
# All pending CPU loads will wait until store buffer is empty to
# ensure strict memory model. Right now this is necessary because
# we don't make destinction between cached and cache inhibited
# address space, so we simply empty store buffer until loads
# can begin.
#
# It makes design a bit bigger, depending what is the number of
# entries in SB FIFO. Number of entries can be changed further
# down.
#
OR1200_SB_IMPLEMENTED = False

#
# Number of store buffer entries
#
# Verified number of entries are 4 and 8 entries
# (2 and 3 for OR1200_SB_LOG). OR1200_SB_ENTRIES must
# always match 2**OR1200_SB_LOG.
# To disable store buffer, undefine OR1200_SB_IMPLEMENTED.
OR1200_SB_LOG = 2	# 2 or 3
OR1200_SB_ENTRIES = 4	# 4 or 8

# Quick Embedded Memory (QMEM)
#
# Quick Embedded Memory
#
# Instantiation of dedicated insn/data memory (RAM or ROM).
# Insn fetch has effective throughput 1insn / clock cycle.
# Data load takes two clock cycles / access, data store
# takes 1 clock cycle / access (if there is no insn fetch)).
# Memory instantiation is shared between insn and data,
# meaning if insn fetch are performed, data load/store
# performance will be lower.
#
# Main reason for QMEM is to put some time critical functions
# into this memory and to have predictable and fast access
# to these functions. (soft fpu, context switch, exception
# handlers, stack, etc)
#
# It makes design a bit bigger and slower. QMEM sits behind
# IMMU/DMMU so all addresses are physical (so the MMUs can be
# used with QMEM and QMEM is seen by the CPU just like any other
# memory in the system). IC/DC are sitting behind QMEM so the
# whole design timing might be worse with QMEM implemented.
OR1200_QMEM_IMPLEMENTED = True
# QMEM interface byte-select capability
#
# To enable qmem_sel* ports, define this macro.
#
OR1200_QMEM_BSEL = False

#
# QMEM interface acknowledge
#
# To enable qmem_ack port, define this macro.
#
OR1200_QMEM_ACK = False


# VR, UPR and Configuration Registers
#
# VR, UPR and configuration registers are optional. If 
# implemented, operating system can automatically figure
# out how to use the processor because it knows 
# what units are available in the processor and how they
# are configured.
#
# This section must be last in or1200_defines.v file so
# that all units are already configured and thus
# configuration registers are properly set.

# Define if you want configuration registers implemented
OR1200_CFGR_IMPLEMENTED = True
#Define if you want full address decode inside SYS group
OR1200_SYS_FULL_DECODE = True

#Offsets of VR, UPR and CFGR registers
OR1200_SPRGRP_SYS_VR, OR1200_SPRGRP_SYS_UPR, OR1200_SPRGRP_SYS_CPUCFGR, OR1200_SPRGRP_SYS_DMMUCFGR, \
    OR1200_SPRGRP_SYS_IMMUCFGR, OR1200_SPRGRP_SYS_DCCFGR, OR1200_SPRGRP_SYS_ICCFGR, OR1200_SPRGRP_SYS_DCFGR \
    = [pyrtl.Const(x, bitwidth=4) for x in range(0x8)]

#VR fields
OR1200_VR_REV_BITS = slice(0, 6) #5:0
OR1200_VR_RES1_BITS = slice(6, 16) #15:6
OR1200_VR_CFG_BITS = slice(16, 24) #23:16
OR1200_VR_VER_BITS = slice(24, 32) #31:24
#VR values
OR1200_VR_REV = pyrtl.Const(0x1, bitwidth=6) #6'h01
OR1200_VR_RES1 = pyrtl.Const(0x0, bitwidth=10) #10'h000
OR1200_VR_CFG = pyrtl.Const(0x0, bitwidth=8) #8'h00
OR1200_VR_VER = pyrtl.Const(0x12, bitwidth=8) #8'h12
#UPR fields
OR1200_UPR_UP_BITS = slice(0, 1) #0
OR1200_UPR_DCP_BITS = slice(1, 2) #1
OR1200_UPR_ICP_BITS = slice(2, 3) #2
OR1200_UPR_DMP_BITS = slice(3, 4) #3
OR1200_UPR_IMP_BITS = slice(4, 5) #4
OR1200_UPR_MP_BITS = slice(5, 6) #5
OR1200_UPR_DUP_BITS = slice(6, 7) #6
OR1200_UPR_PCUP_BITS = slice(7, 8) #7
OR1200_UPR_PMP_BITS = slice(8, 9) #8
OR1200_UPR_PICP_BITS = slice(9, 10) #9
OR1200_UPR_TTP_BITS = slice(10, 11) #10
OR1200_UPR_RES1_BITS = slice(11, 24) #23:11
OR1200_UPR_CUP_BITS = slice(24, 32) #31:24
#UPR values
OR1200_UPR_UP = pyrtl.Const(1, bitwidth=1) #1'b1
if OR1200_NO_DC:
    OR1200_UPR_DCP = pyrtl.Const(0, bitwidth=1) #1'b0
else:
    OR1200_UPR_DCP = pyrtl.Const(1, bitwidth=1) #1'b1

OR1200_NO_IC = False
if OR1200_NO_IC:
    OR1200_UPR_ICP = pyrtl.Const(0, bitwidth=1) #1'b0
else:
    OR1200_UPR_ICP = pyrtl.Const(1, bitwidth=1)  #1'b1

OR1200_UPR_MP = pyrtl.Const(1, bitwidth=1)  #1'b1	# MAC always present
if OR1200_DU_IMPLEMENTED:
    OR1200_UPR_DUP = pyrtl.Const(1, bitwidth=1)  # 1'b1
    OR1200_UPR_PMP = pyrtl.Const(1, bitwidth=1)  # 1'b1
    OR1200_UPR_PICP = pyrtl.Const(1, bitwidth=1)  # 1'b1
    OR1200_UPR_TTP = pyrtl.Const(1, bitwidth=1)  # 1'b1
else:
    OR1200_UPR_DUP = pyrtl.Const(0, bitwidth=1)  # 1'b0
    OR1200_UPR_PMP = pyrtl.Const(0, bitwidth=1)  # 1'b0
    OR1200_UPR_PICP = pyrtl.Const(0, bitwidth=1)  # 1'b0
    OR1200_UPR_TTP = pyrtl.Const(0, bitwidth=1)  # 1'b0

OR1200_UPR_PCUP = pyrtl.Const(0, bitwidth=1)  #1'b0	// Performance counters not present
OR1200_UPR_RES1 = pyrtl.Const(0x0, bitwidth=13) #13'h0000
OR1200_UPR_CUP = pyrtl.Const(0x0, bitwidth=8) #8'h00

#CPUCFGR fields
OR1200_CPUCFGR_NSGF_BITS = slice(0, 4) #3:0
OR1200_CPUCFGR_HGF_BITS = slice(4, 5) #4
OR1200_CPUCFGR_OB32S_BITS = slice(5, 6) #5
OR1200_CPUCFGR_OB64S_BITS = slice(6, 7) #6
OR1200_CPUCFGR_OF32S_BITS = slice(7, 8) #7
OR1200_CPUCFGR_OF64S_BITS = slice(8, 9) #8
OR1200_CPUCFGR_OV64S_BITS = slice(9, 10) #9
OR1200_CPUCFGR_RES1_BITS = slice(10, 32) #31:10

#CPUCFGR values
OR1200_CPUCFGR_NSGF = pyrtl.Const(0x0, bitwidth=4) #4'h0
OR1200_CPUCFGR_HGF = pyrtl.Const(0b0, bitwidth=1) #1'b0
OR1200_CPUCFGR_OB32S = pyrtl.Const(0b1, bitwidth=1) #1'b1
OR1200_CPUCFGR_OB64S = pyrtl.Const(0b0, bitwidth=1) #1'b0
OR1200_CPUCFGR_OF32S = pyrtl.Const(0b0, bitwidth=1) #1'b0
OR1200_CPUCFGR_OF64S = pyrtl.Const(0b0, bitwidth=1) #1'b0
OR1200_CPUCFGR_OV64S = pyrtl.Const(0b0, bitwidth=1) #1'b0
OR1200_CPUCFGR_RES1 = pyrtl.Const(0x0, bitwidth=22) #22'h000000

#DCCFGR fields
OR1200_DCCFGR_NCW_BITS = slice(0, 3) #2:0
OR1200_DCCFGR_NCS_BITS = slice(3, 7) #6:3
OR1200_DCCFGR_CBS_BITS = slice(7, 8) #7
OR1200_DCCFGR_CWS_BITS = slice(8, 9) #8
OR1200_DCCFGR_CCRI_BITS = slice(9, 10) #9
OR1200_DCCFGR_CBIRI_BITS = slice(10, 11) #10
OR1200_DCCFGR_CBPRI_BITS = slice(11, 12) #11
OR1200_DCCFGR_CBLRI_BITS = slice(12, 13) #12
OR1200_DCCFGR_CBFRI_BITS = slice(13, 14) #13
OR1200_DCCFGR_CBWBRI_BITS = slice(14, 15) #14
OR1200_DCCFGR_RES1_BITS = slice(15, 32) #31:15

#DCCFGR values
if OR1200_NO_DC:
    OR1200_DCCFGR_NCW = pyrtl.Const(0x0, bitwidth=3) #3'h0	// Irrelevant
    OR1200_DCCFGR_NCS = pyrtl.Const(0x0, bitwidth=4) #4'h0	// Irrelevant
    OR1200_DCCFGR_CBS = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_DCCFGR_CWS = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_DCCFGR_CCRI = pyrtl.Const(0b1, bitwidth=1) #1'b1	// Irrelevant
    OR1200_DCCFGR_CBIRI = pyrtl.Const(0b1, bitwidth=1) #1'b1	// Irrelevant
    OR1200_DCCFGR_CBPRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_DCCFGR_CBLRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_DCCFGR_CBFRI = pyrtl.Const(0b1, bitwidth=1) #1'b1	// Irrelevant
    OR1200_DCCFGR_CBWBRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_DCCFGR_RES1 = pyrtl.Const(0x0, bitwidth=17) #17'h00000
else:
    OR1200_DCCFGR_NCW = pyrtl.Const(0x0, bitwidth=3) #3'h0	// 1 cache way
    #OR1200_DCCFGR_NCS = OR1200_DCTAG #(`OR1200_DCTAG)	// Num cache sets
    #OR1200_DCCFGR_CBS = OR1200_DCLS - 4#   (`OR1200_DCLS-4)	// 16 byte cache block
    OR1200_DCCFGR_CWS = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Write-through strategy
    OR1200_DCCFGR_CCRI = pyrtl.Const(0b1, bitwidth=1) #1'b1	// Cache control reg impl.
    OR1200_DCCFGR_CBIRI = pyrtl.Const(0b1, bitwidth=1) #1'b1	// Cache block inv reg impl.
    OR1200_DCCFGR_CBPRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Cache block prefetch reg not impl.
    OR1200_DCCFGR_CBLRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Cache block lock reg not impl.
    OR1200_DCCFGR_CBFRI = pyrtl.Const(0b1, bitwidth=1) #1'b1	// Cache block flush reg impl.
    OR1200_DCCFGR_CBWBRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Cache block WB reg not impl.
    OR1200_DCCFGR_RES1 = pyrtl.Const(0x0, bitwidth=17) #17'h00000

#ICCFGR fields
OR1200_ICCFGR_NCW_BITS = slice(0, 3) #2:0
OR1200_ICCFGR_NCS_BITS = slice(3, 7) #6:3
OR1200_ICCFGR_CBS_BITS = slice(7, 8) #7
OR1200_ICCFGR_CWS_BITS = slice(8, 9) #8
OR1200_ICCFGR_CCRI_BITS = slice(9, 10) #9
OR1200_ICCFGR_CBIRI_BITS = slice(10, 11) #10
OR1200_ICCFGR_CBPRI_BITS = slice(11, 12) #11
OR1200_ICCFGR_CBLRI_BITS = slice(12, 13) #12
OR1200_ICCFGR_CBFRI_BITS = slice(13, 14) #13
OR1200_ICCFGR_CBWBRI_BITS = slice(14, 15) #14
OR1200_ICCFGR_RES1_BITS = slice(15, 32) #31:15

#ICCFGR values
if OR1200_NO_IC:
    OR1200_ICCFGR_NCW = pyrtl.Const(0x0, bitwidth=3) #3'h0	// Irrelevant
    OR1200_ICCFGR_NCS = pyrtl.Const(0x0, bitwidth=4) #4'h0	// Irrelevant
    OR1200_ICCFGR_CBS = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_ICCFGR_CWS = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_ICCFGR_CCRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_ICCFGR_CBIRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_ICCFGR_CBPRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_ICCFGR_CBLRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_ICCFGR_CBFRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_ICCFGR_CBWBRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_ICCFGR_RES1 = pyrtl.Const(0x0, bitwidth=17) #17'h00000
else:
    OR1200_ICCFGR_NCW = pyrtl.Const(0x0, bitwidth=3) #3'h0	// 1 cache way
    #OR1200_ICCFGR_NCS = OR1200_ICTAG # (`OR1200_ICTAG)	// Num cache sets
    #OR1200_ICCFGR_CBS = OR1200_ICLS - 4 # (`OR1200_ICLS-4)	// 16 byte cache block
    OR1200_ICCFGR_CWS = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_ICCFGR_CCRI = pyrtl.Const(0b1, bitwidth=1) #1'b1	// Cache control reg impl.
    OR1200_ICCFGR_CBIRI = pyrtl.Const(0b1, bitwidth=1) #1'b1	// Cache block inv reg impl.
    OR1200_ICCFGR_CBPRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Cache block prefetch reg not impl.
    OR1200_ICCFGR_CBLRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Cache block lock reg ot impl.
    OR1200_ICCFGR_CBFRI = pyrtl.Const(0b1, bitwidth=1) #1'b1	// Cache block flush reg impl.
    OR1200_ICCFGR_CBWBRI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// Irrelevant
    OR1200_ICCFGR_RES1 = pyrtl.Const(0x0, bitwidth=17) #17'h00000

#DCFGR fields
OR1200_DCFGR_NDP_BITS = slice(0, 3) #2:0
OR1200_DCFGR_WPCI_BITS = slice(3, 4) #3
OR1200_DCFGR_RES1_BITS = slice(4, 32) #31:4

#DCFGR values
if OR1200_DU_HWBKPTS:
    OR1200_DCFGR_NDP = pyrtl.Const(OR1200_DU_DVRDCR_PAIRS, bitwidth=3) #3'h`OR1200_DU_DVRDCR_PAIRS // # of DVR/DCR pairs
    if OR1200_DU_DWCR0:
        OR1200_DCFGR_WPCI = pyrtl.Const(0b1, bitwidth=1) #1'b1
    else:
        OR1200_DCFGR_WPCI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// WP counters not impl.
else:
    OR1200_DCFGR_NDP = pyrtl.Const(0x0, bitwidth=3) #3'h0	// Zero DVR/DCR pairs
    OR1200_DCFGR_WPCI = pyrtl.Const(0b0, bitwidth=1) #1'b0	// WP counters not impl.

OR1200_DCFGR_RES1 = pyrtl.Const(0x0, bitwidth=28) #28'h0000000

ONE = pyrtl.Const(0b1, bitwidth=1)
ZERO = pyrtl.Const(0b0, bitwidth=1)

def LeftLogicalShifter( in0, shamt ):
  out = pyrtl.WireVector( len(in0) )
  # Damn it doesn't support shifting!
  # out <<= in0 << shamt
  # concat is
  out <<= pyrtl.concat( in0[:-shamt], pyrtl.Const( 0, bitwidth=shamt ) )
  return out

def RightLogicalShifter( in0, shamt ):
  out = pyrtl.WireVector( len(in0) )
  # Damn it doesn't support shifting!
  # out <<= in0 >> shamt
  out <<= pyrtl.concat( pyrtl.Const(0, bitwidth=shamt), in0[shamt:] )

  return out

#Reduction operators
def Or_Not(wirevector):
    wire0 = wirevector[0]
    for i in wirevector:
        wire0 = wire0 | i
    return wire0 == ZERO

def Or(wirevector):
    wire0 = wirevector[0]
    for i in wirevector:
        wire0 = wire0 | i
    return wire0

OR1200_EXCEPTFSM_IDLE = pyrtl.Const(0)
OR1200_EXCEPTFSM_FLU1 = pyrtl.Const(0)
OR1200_EXCEPTFSM_FLU2 = pyrtl.Const(0)
OR1200_EXCEPTFSM_FLU3 = pyrtl.Const(0)
OR1200_EXCEPTFSM_FLU4 = pyrtl.Const(0)
OR1200_EXCEPTFSM_FLU5 = pyrtl.Const(0)